x86/mcheck: do not blindly de-reference dom0 et al
authorKeir Fraser <keir.fraser@citrix.com>
Wed, 17 Feb 2010 12:04:50 +0000 (12:04 +0000)
committerKeir Fraser <keir.fraser@citrix.com>
Wed, 17 Feb 2010 12:04:50 +0000 (12:04 +0000)
Since machine checks and CMCIs can happen before Dom0 even gets
constructed, the handlers of these events have to avoid de-referencing
respective pointers without checking.

Signed-off-by: Jan Beulich <jbeulich@novell.com>
xen/arch/x86/cpu/mcheck/amd_nonfatal.c
xen/arch/x86/cpu/mcheck/mce.c
xen/arch/x86/cpu/mcheck/mce.h
xen/arch/x86/cpu/mcheck/mce_intel.c
xen/arch/x86/cpu/mcheck/non-fatal.c

index f2fedcd29971bcc44b31c7ad0167a37fbd7bc8c2..68d2e1fee6ec2d8fd6bf6c7bddec1b1290cc733a 100644 (file)
@@ -84,12 +84,9 @@ static void mce_amd_checkregs(void *info)
 {
        mctelem_cookie_t mctc;
        struct mca_summary bs;
-       unsigned int event_enabled;
 
        mctc = mcheck_mca_logout(MCA_POLLER, mca_allbanks, &bs, NULL);
 
-       event_enabled = guest_enabled_event(dom0->vcpu[0], VIRQ_MCA);
-
        if (bs.errcnt && mctc != NULL) {
                static uint64_t dumpcount = 0;
 
@@ -101,7 +98,7 @@ static void mce_amd_checkregs(void *info)
                 * a simple-minded attempt to avoid spamming the console
                 * for corrected errors in early startup. */
 
-               if (event_enabled) {
+               if (dom0_vmce_enabled()) {
                        mctelem_commit(mctc);
                        send_guest_global_virq(dom0, VIRQ_MCA);
                } else if (++dumpcount >= 10) {
@@ -136,7 +133,7 @@ static void mce_amd_work_fn(void *data)
        on_each_cpu(mce_amd_checkregs, data, 1);
 
        if (adjust > 0) {
-               if (!guest_enabled_event(dom0->vcpu[0], VIRQ_MCA) ) {
+               if (!dom0_vmce_enabled()) {
                        /* Dom0 did not enable VIRQ_MCA, so Xen is reporting. */
                        printk("MCE: polling routine found correctable error. "
                                " Use mcelog to parse above error output.\n");
index d5b404aba68889c4f8f99e46993e7df6023d5c3f..955ed7b78f89c1e9ad6192133cb94ba1906a5d1c 100644 (file)
@@ -414,7 +414,7 @@ void mcheck_cmn_handler(struct cpu_user_regs *regs, long error_code,
         * as terminal for any context.
         */
        ctx_xen = SEG_PL(regs->cs) == 0;
-       ctx_dom0 = !ctx_xen && (domid == dom0->domain_id);
+       ctx_dom0 = !ctx_xen && (domid == 0);
        ctx_domU = !ctx_xen && !ctx_dom0;
 
        xen_state_lost = bs.uc != 0 || (ctx_xen && (bs.pcc || !ripv)) ||
@@ -463,7 +463,8 @@ void mcheck_cmn_handler(struct cpu_user_regs *regs, long error_code,
         * XXFM Could add some Solaris dom0 contract kill here?
         */
        if (dom0_state_lost) {
-               if (guest_has_trap_callback(dom0, 0, TRAP_machine_check)) {
+               if (dom0 && dom0->max_vcpus && dom0->vcpu[0] &&
+                   guest_has_trap_callback(dom0, 0, TRAP_machine_check)) {
                        dom_state = DOM0_TRAP;
                        send_guest_trap(dom0, 0, TRAP_machine_check);
                        /* XXFM case of return with !ripv ??? */
@@ -532,7 +533,7 @@ cmn_handler_done:
        if (bs.errcnt) {
                /* Not panicing, so forward telemetry to dom0 now if it
                 * is interested. */
-               if (guest_enabled_event(dom0->vcpu[0], VIRQ_MCA)) {
+               if (dom0_vmce_enabled()) {
                        if (mctc != NULL)
                                mctelem_commit(mctc);
                        send_guest_global_virq(dom0, VIRQ_MCA);
index 6a8c8c85b3b8e65ed59e6bc50d74e3faf3f87a64..cfc26abf4cc81e667f25ea83fef3e286395ca7ea 100644 (file)
@@ -55,6 +55,8 @@ void mc_panic(char *s);
 void x86_mc_get_cpu_info(unsigned, uint32_t *, uint16_t *, uint16_t *,
                         uint32_t *, uint32_t *, uint32_t *, uint32_t *);
 
+#define dom0_vmce_enabled() (dom0 && dom0->max_vcpus && dom0->vcpu[0] \
+       && guest_enabled_event(dom0->vcpu[0], VIRQ_MCA))
 
 /* Register a handler for machine check exceptions. */
 typedef void (*x86_mce_vector_t)(struct cpu_user_regs *, long);
index be44dcf71cefc96543a81f1be55765505b077fff..b8b64921ac3f414b55b783579b955361628c39c3 100644 (file)
@@ -518,7 +518,7 @@ static void mce_softirq(void)
         }
 
         /* Step2: Send Log to DOM0 through vIRQ */
-        if (dom0 && guest_enabled_event(dom0->vcpu[0], VIRQ_MCA)) {
+        if (dom0_vmce_enabled()) {
             mce_printk(MCE_VERBOSE, "MCE: send MCE# to DOM0 through virq\n");
             send_guest_global_virq(dom0, VIRQ_MCA);
         }
@@ -864,7 +864,7 @@ static void cmci_discover(void)
         MCA_CMCI_HANDLER, __get_cpu_var(mce_banks_owned), &bs, NULL);
 
     if (bs.errcnt && mctc != NULL) {
-        if (guest_enabled_event(dom0->vcpu[0], VIRQ_MCA)) {
+        if (dom0_vmce_enabled()) {
             mctelem_commit(mctc);
             send_guest_global_virq(dom0, VIRQ_MCA);
         } else {
@@ -979,7 +979,7 @@ fastcall void smp_cmci_interrupt(struct cpu_user_regs *regs)
         MCA_CMCI_HANDLER, __get_cpu_var(mce_banks_owned), &bs, NULL);
 
     if (bs.errcnt && mctc != NULL) {
-        if (guest_enabled_event(dom0->vcpu[0], VIRQ_MCA)) {
+        if (dom0_vmce_enabled()) {
             mctelem_commit(mctc);
             mce_printk(MCE_VERBOSE, "CMCI: send CMCI to DOM0 through virq\n");
             send_guest_global_virq(dom0, VIRQ_MCA);
index 5a2f8a40065acb51e6c3affc724946a05791d16d..124d4aa504d103cbd7170592eed4cdc7a35d4f41 100644 (file)
@@ -53,7 +53,7 @@ static void mce_checkregs (void *info)
                 * for corrected errors in early startup.
                 */
 
-               if (guest_enabled_event(dom0->vcpu[0], VIRQ_MCA)) {
+               if (dom0_vmce_enabled()) {
                        mctelem_commit(mctc);
                        send_guest_global_virq(dom0, VIRQ_MCA);
                } else if (++dumpcount >= 10) {